package com.atguigu.product.service.impl;

import com.atguigu.clients.CategoryClient;
import com.atguigu.param.ProductHotParam;
import com.atguigu.param.ProductIdsParam;
import com.atguigu.pojo.Picture;
import com.atguigu.pojo.Product;
import com.atguigu.product.mapper.PictureMapper;
import com.atguigu.product.mapper.ProductMapper;
import com.atguigu.product.service.ProductService;
import com.atguigu.utils.R;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author 张三禾
 * @create 2023-03-12 12:30
 * @Description 类别的实现类
 */
@Slf4j
@Service
public class ProductServiceImpl implements ProductService {

    //引入feign客户端需要在启动类添加配置注解
    @Autowired
    private CategoryClient categoryClient;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private PictureMapper pictureMapper;

    /**
     * 根据单类别名称查询热门药品，最多7条数据
     * 1. 根据类别名称调用feign客户端，访问类别服务，获取类别数据
     * 2. 成功，继续根据类别id查询药品数据【热门 销售量倒序】
     * 3. 结果封装即可
     * @param categoryName
     * @return
     */
    //feign一般都在业务层进行调用

    @Override
    public R promo(String categoryName) {
        R r = categoryClient.byName(categoryName);

        if (r.getCode().equals(R.FAIL_CODE)) {
            log.info("ProductServiceImpl.promo业务结束，结果：{}", "类别查询失败");
            return r;
        }

//        Category category = (Category) r.getData();
//        Integer categoryId = category.getCategoryId();
        LinkedHashMap<String,Object> map = (LinkedHashMap<String, Object>) r.getData();
        Integer categoryId = (Integer)map.get("category_id");

        //封装查询参数
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("category_id",categoryId);
        queryWrapper.orderByDesc("product_sales");

        //分页current:当前页数 size：条数
        IPage<Product> page = new Page<>(1,7);
        //返回的是包装数据！内部有对应的药品集合，也有分页的参数 例如：总条数、总页数等等
        page = productMapper.selectPage(page, queryWrapper);
        //获取指定的分页数据
        List<Product> productList = page.getRecords();
        //获取总条数
        long total = page.getTotal();

        log.info("ProductServiceImpl.promo业务结束，结果：{}", productList);
        return R.ok("数据查询成功！",productList);
    }

    /**
     * 多类别热门药品查询 根据类别名称集合! 至多查询7条!
     *   1. 调用类别服务
     *   2. 类别集合id查询药品
     *   3. 结果集封装即可
     * @param productHotParam 类别名称集合
     * @return r
     */
    @Cacheable(value = "list.product",key = "#productHotParam.categoryName")
    @Override
    public R hots(ProductHotParam productHotParam) {

        //通过feign调用类别查询id集合
        R r = categoryClient.hots(productHotParam);

        //校验：通过返回r的校验码校验类别查询是否成功
        if(r.getCode().equals(R.FAIL_CODE)){
            log.info("ProductServiceImpl.hots业务结束，结果:{}",r.getMsg());
            return r;
        }

        List<Object> ids = (List<Object>) r.getData();

        //进行药品数据查询的参数封装，根据id的列表降序
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("category_id",ids);
        queryWrapper.orderByDesc("product_sales");

        //分页插件：selectPage是MyBatis-Plus中提供的一个分页查询方法，用于在查询时进行分页，并返回一个Page对象，该对象包含了当前页码、每页记录数、总记录数等信息。
        IPage<Product> page = new Page<>(1,7);
        page = productMapper.selectPage(page,queryWrapper);

        List<Product> records = page.getRecords();

        R ok = R.ok("多类别热门药品查询成功!", records);

        log.info("ProductServiceImpl.hots业务结束，结果:{}",ok);

        return ok;
    }

    /**
     * 查询类别商品集合
     *
     * @return
     */
    @Override
    public R clist() {
        R r = categoryClient.list();
        log.info("ProductServiceImpl.clist业务结束，结果:{}",r);

        return r;
    }

    /**
     * 通用性的业务!
     * 传入了类别id,根据id查询并且分页
     * 没有传入类别的id! 查询全部!
     *
     * @param productIdsParam
     * @return
     */
    @Cacheable(value = "list.product",key = "#productIdsParam.categoryID+'-'+#productIdsParam.currentPage+'-'+#productIdsParam.pageSize")
    @Override
    public R byCategory(ProductIdsParam productIdsParam) {

        //获取id的集合，可能为空集合
        List<Integer> categoryID = productIdsParam.getCategoryID();

        //封装参数，不为空装id的集合列表
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        if (!categoryID.isEmpty()) {
            queryWrapper.in("category_id",categoryID);
        }

        //参数说明：当前页和页容量
        IPage<Product> page = new Page<>(productIdsParam.getCurrentPage(),productIdsParam.getPageSize());

        page = productMapper.selectPage(page,queryWrapper);

        //结果集封装
        R ok = R.ok("查询成功!", page.getRecords(), page.getTotal());

        log.info("ProductServiceImpl.byCategory业务结束，结果:{}",ok);

        return ok;
    }

    /**
     * 根据商品id,查询商品详情信息
     *
     * @param productID
     * @return
     */
    @Cacheable(value = "product",key = "#productID")
    @Override
    public R detail(Integer productID) {


        Product product = productMapper.selectById(productID);

        R ok = R.ok(product);
        log.info("ProductServiceImpl.detail业务结束，结果:{}",ok);
        return ok;
    }

    /**
     * 查询商品对应的图片详情集合
     *
     * @param productID
     * @return
     */
    @Cacheable(value="picture",key = "#productID")
    @Override
    public R pictures(Integer productID) {

        //封装参数
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id",productID);

        //用selectList查询，根据
        List<Picture> pictureList = pictureMapper.selectList(queryWrapper);

        //将结果集合封装到R中
        R ok = R.ok(pictureList);

        log.info("ProductServiceImpl.pictures业务结束，结果:{}",ok);
        return ok;
    }

    /**
     * 搜索服务调用,获取全部商品数据!
     * 进行同步!
     *
     * @return 商品数据集合
     */
    @Cacheable(value = "list.category",key = "#root.methodName",cacheManager = "cacheManagerDay")
    @Override
    public List<Product> allList() {

        List<Product> productList = productMapper.selectList(null);
        log.info("ProductServiceImpl.allList业务结束，结果:{}",productList.size());
        return productList;
    }
}
